package com.github.caijh.mall.marketing.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.caijh.commons.util.Collections;
import com.github.caijh.commons.util.DateUtils;
import com.github.caijh.commons.util.Strings;
import com.github.caijh.mall.category.model.Category;
import com.github.caijh.mall.category.service.CategoryService;
import com.github.caijh.mall.common.PageParams;
import com.github.caijh.mall.exception.CrmebException;
import com.github.caijh.mall.marketing.dao.StoreCouponDao;
import com.github.caijh.mall.marketing.model.StoreCoupon;
import com.github.caijh.mall.marketing.model.StoreCouponUser;
import com.github.caijh.mall.marketing.request.StoreCouponRequest;
import com.github.caijh.mall.marketing.request.StoreCouponSearchRequest;
import com.github.caijh.mall.marketing.response.StoreCouponFrontResponse;
import com.github.caijh.mall.marketing.response.StoreCouponInfoResponse;
import com.github.caijh.mall.marketing.service.StoreCouponService;
import com.github.caijh.mall.marketing.service.StoreCouponUserService;
import com.github.caijh.mall.store.model.StoreProduct;
import com.github.caijh.mall.store.request.StoreProductSearchReqBody;
import com.github.caijh.mall.store.service.StoreProductService;
import com.github.caijh.mall.utils.Utils;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * StoreCouponServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Service
public class StoreCouponServiceImpl extends ServiceImpl<StoreCouponDao, StoreCoupon> implements StoreCouponService {

    @Resource
    private StoreCouponDao dao;

    @Autowired
    private StoreProductService storeProductService;

    @Autowired
    private StoreCouponUserService storeCouponUserService;

    @Autowired
    private CategoryService categoryService;


    /**
     * 列表
     *
     * @param request    请求参数
     * @param pageParams 分页类参数
     * @return List<StoreCoupon>
     * @author Mr.Zhang
     * @since 2020-05-18
     */
    @Override
    public List<StoreCoupon> getList(StoreCouponSearchRequest request, PageParams pageParams) {
        PageHelper.startPage(pageParams.getPage(), pageParams.getLimit());

        //带 StoreCoupon 类的多条件查询
        LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (null != request.getIsDel()) {
            lambdaQueryWrapper.eq(StoreCoupon::getIsDel, request.getIsDel());
        }

        if (null != request.getType()) {
            lambdaQueryWrapper.eq(StoreCoupon::getType, request.getType());
        }

        if (null != request.getStatus()) {
            lambdaQueryWrapper.eq(StoreCoupon::getStatus, request.getStatus());
        }

        if (StringUtils.isNotBlank(request.getName())) {
            lambdaQueryWrapper.like(StoreCoupon::getName, request.getName());
        }

        if (StringUtils.isNotBlank(request.getPrimaryKey())) {
            lambdaQueryWrapper.apply(Utils.getFindInSetSql("primary_key", request.getPrimaryKey()) + " and use_type = " + request.getUseType());
        }

        lambdaQueryWrapper.orderByDesc(StoreCoupon::getSort).orderByDesc(StoreCoupon::getId);
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 保存优惠券表
     *
     * @param request StoreCouponRequest 新增参数
     * @author Mr.Zhang
     * @since 2020-05-18
     */
    @Override
    public boolean create(StoreCouponRequest request) {
        StoreCoupon storeCoupon = new StoreCoupon();
        BeanUtils.copyProperties(request, storeCoupon);
        if (storeCoupon.getIsLimited() && (storeCoupon.getTotal() == null || storeCoupon.getTotal() == 0)) {
            throw new CrmebException("请输入数量！");
        }

        if (request.getUseType() > 1 && (StringUtils.isBlank(request.getPrimaryKey()))) {
            throw new CrmebException("请选择商品/分类！");
        }

        storeCoupon.setLastTotal(storeCoupon.getTotal());
        if (!request.getIsForever()) {
            storeCoupon.setReceiveStartTime(DateUtils.now()); //开始时间设置为当前时间
        } else {
            if (storeCoupon.getReceiveStartTime() == null || storeCoupon.getReceiveEndTime() == null) {
                throw new CrmebException("请选择领取时间范围！");
            }

            if (storeCoupon.getReceiveEndTime().before(storeCoupon.getReceiveStartTime())) {
                throw new CrmebException("请选择正确的领取时间范围！");
            }
        }

        //非固定时间, 领取后多少天
        if (!request.getIsFixedTime()) {
            if (storeCoupon.getDay() == null || storeCoupon.getDay() == 0) {
                throw new CrmebException("请输入天数！");
            }
            storeCoupon.setUseStartTime(null);
            storeCoupon.setUseEndTime(null);
        }
        return save(storeCoupon);
    }

    /**
     * 获取详情
     *
     * @param id Integer id
     * @return StoreCoupon
     * @author Mr.Zhang
     * @since 2020-05-18
     */
    @Override
    public StoreCoupon getInfoException(Integer id) {
        //获取优惠券信息
        StoreCoupon storeCoupon = getById(id);
        checkException(storeCoupon);

        return storeCoupon;
    }

    /**
     * 检测当前优惠券是否正常
     *
     * @param storeCoupon StoreCoupon 优惠券对象`
     * @author Mr.Zhang
     * @since 2020-05-18
     */
    @Override
    public void checkException(StoreCoupon storeCoupon) {
        if (storeCoupon == null || storeCoupon.getIsDel() || !storeCoupon.getStatus()) {
            throw new CrmebException("优惠券信息不存在或者已失效！");
        }

        //看是否过期
        if (storeCoupon.getReceiveEndTime() != null && DateUtils.now().after(storeCoupon.getReceiveEndTime())) {
            throw new CrmebException("已超过优惠券领取最后期限！");
        }

        //看是否有剩余数量
        if (storeCoupon.getIsLimited() != null && storeCoupon.getIsLimited()
                && storeCoupon.getLastTotal() < 1) {
            //考虑到并发溢出的问题用大于等于
            throw new CrmebException("此优惠券已经被领完了！");
        }
    }

    /**
     * 用户是否有可以领取的优惠券
     *
     * @param idList List<Integer> id集合
     * @return List<StoreCoupon>
     * @author Mr.Zhang
     * @since 2020-05-18
     */
    @Override
    public List<StoreCoupon> getReceiveListInId(List<Integer> idList) {
        //带 StoreCoupon 类的多条件查询
        LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        //状态
        lambdaQueryWrapper.in(StoreCoupon::getId, idList)
                          .eq(StoreCoupon::getIsDel, false)
                          .eq(StoreCoupon::getStatus, true);

        //数量不限量或者大于0
        lambdaQueryWrapper.and(i -> i.or().eq(StoreCoupon::getIsLimited, 0).or().lt(StoreCoupon::getLastTotal, 0));

        //可领取时间
        lambdaQueryWrapper.lt(StoreCoupon::getReceiveEndTime, DateUtils.now());

        return dao.selectList(lambdaQueryWrapper);
    }

//    /**
//     * 根据商品id获取可用优惠券列表
//     * @param productId 获取可用优惠券的商品id
//     * @return 商品对应的可用优惠券集合
//     */
//    @Override
//    public List<StoreCoupon> getListByProductCanUse(Integer productId) {
//
//        List<Integer> categoryIdList = storeProductService.getSecondaryCategoryByProductId(productId);
//
//        LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(StoreCoupon::getIsDel, false);
//        lambdaQueryWrapper.eq(StoreCoupon::getType, 1);
//        lambdaQueryWrapper.eq(StoreCoupon::getIsLimited, true);
//        lambdaQueryWrapper.ge(StoreCoupon::getLastTotal, 0);
//        //有商品id  通用券可以领取，商品券可以领取，分类券可以领取
//        lambdaQueryWrapper.apply(getPrimaryKeySql(productId));
//        return dao.selectList(lambdaQueryWrapper);
//    }

    /**
     * 优惠券详情
     *
     * @param id Integer 获取可用优惠券的商品id
     * @return StoreCouponInfoResponse
     */
    @Override
    public StoreCouponInfoResponse info(Integer id) {
        try {
            StoreCoupon storeCoupon = getById(id);
            if (storeCoupon == null || storeCoupon.getIsDel() || !storeCoupon.getStatus()) {
                throw new CrmebException("优惠券信息不存在或者已失效！");
            }

            List<StoreProduct> productList = null;
            List<Category> categoryList = null;
            if (StringUtils.isNotBlank(storeCoupon.getPrimaryKey()) && storeCoupon.getUseType() > 1) {
                List<Integer> primaryIdList = Strings.toIntListByComma(storeCoupon.getPrimaryKey());
                if (storeCoupon.getUseType() == 2) {
                    productList = storeProductService.page(new StoreProductSearchReqBody(), new PageParams(), primaryIdList);
                }
                if (storeCoupon.getUseType() == 3) {
                    categoryList = categoryService.getByIds(primaryIdList);
                }
            }

            StoreCouponRequest coupon = new StoreCouponRequest();
            BeanUtils.copyProperties(storeCoupon, coupon);
            coupon.setIsForever(false);
            if (null != coupon.getReceiveEndTime()) {
                coupon.setIsForever(true);
            }

            return new StoreCouponInfoResponse(coupon, productList, categoryList);
        } catch (Exception e) {
            throw new CrmebException(e.getMessage());
        }
    }

    @Override
    public List<StoreCouponFrontResponse> getListByUser(Integer productId, PageParams pageParams, Integer userId) {
        List<StoreCoupon> list = getListByReceive(productId, pageParams);
        if (Collections.isEmpty(list)) {
            return Collections.emptyList();
        }
        //获取用户当前已领取未使用的优惠券
        HashMap<Integer, StoreCouponUser> couponUserMap = null;

        if (userId > 0) {
            couponUserMap = storeCouponUserService.getMapByUserId(userId);
        }
        List<StoreCouponFrontResponse> storeCouponFrontResponseArrayList = new ArrayList<>();
        for (StoreCoupon storeCoupon : list) {
            StoreCouponFrontResponse response = new StoreCouponFrontResponse();
            BeanUtils.copyProperties(storeCoupon, response);
            if (null != couponUserMap && couponUserMap.containsKey(storeCoupon.getId())) {
                response.setIsUse(true);
            }

            if (response.getReceiveEndTime() == null) {
                response.setReceiveStartTime(null);
            }

            storeCouponFrontResponseArrayList.add(response);
        }

        return storeCouponFrontResponseArrayList;
    }


    /**
     * 根据优惠券id获取
     *
     * @param ids 优惠券id集合
     * @return
     */
    @Override
    public List<StoreCoupon> getByIds(List<Integer> ids) {
        LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(StoreCoupon::getId, ids);
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 用户可领取的优惠券
     *
     * @return List<StoreCoupon>
     * @author Mr.Zhang
     * @since 2020-05-18
     */
    private List<StoreCoupon> getListByReceive(Integer productId, PageParams pageParams) {
        PageHelper.startPage(pageParams.getPage(), pageParams.getLimit());
        Date date = DateUtils.now();
        //带 StoreCoupon 类的多条件查询
        LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreCoupon::getIsDel, false)
                          .eq(StoreCoupon::getStatus, 1)
                          //剩余数量大于0 或者不设置上限
                          .and(i -> i.gt(StoreCoupon::getLastTotal, 0).or().eq(StoreCoupon::getIsLimited, false))
                          //领取时间范围, 结束时间为null则是不限时
                          .and(i -> i.isNull(StoreCoupon::getReceiveEndTime)
                                     .or(p -> p.lt(StoreCoupon::getReceiveStartTime, date).gt(StoreCoupon::getReceiveEndTime, date)));
        if (productId > 0) {
            //有商品id  通用券可以领取，商品券可以领取，分类券可以领取
            getPrimaryKeySql(lambdaQueryWrapper, productId.toString());
        }

        lambdaQueryWrapper.orderByDesc(StoreCoupon::getSort).orderByDesc(StoreCoupon::getId);
        return dao.selectList(lambdaQueryWrapper);
    }

    private void getPrimaryKeySql(LambdaQueryWrapper<StoreCoupon> lambdaQueryWrapper, String productIdStr) {
        if (StringUtils.isBlank(productIdStr)) {
            return;
        }

        List<Integer> categoryIdList = storeProductService.getSecondaryCategoryByProductId(productIdStr);
        lambdaQueryWrapper.and(i -> i.and(
                //通用券  商品券  品类券
                t -> t.eq(StoreCoupon::getUseType, 1)
                      .or(p -> p.eq(StoreCoupon::getUseType, 2).apply(Utils.getFindInSetSql("primary_key", productIdStr)))
                      .or(c -> c.eq(StoreCoupon::getUseType, 3)
                                .apply(Collections.isNotEmpty(categoryIdList), Utils.getFindInSetSql("primary_key", categoryIdList)))
        ));
    }

}

